package com.zhou.framework.config;

import com.zhou.framework.constant.CacheKeyEnum;
import com.zhou.framework.redis.util.RedisUtil;
import com.zhou.util.EncryptUtil;
import com.zhou.util.NumberUtil;
import com.zhou.util.ObjectUtil;
import com.zhou.util.StringTool;
import com.zhou.org.dao.Setting;
import com.zhou.org.service.SettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 从数据库参数表中缓存参数
 */
@Configuration
@Slf4j
public class DbSettingConfig {
    private SettingService settingService;
    private RedisUtil redisUtil;
    private Map<String,Map<String,String>> localSettingMap = new HashMap<>(10);

    public DbSettingConfig(RedisUtil redisUtil,SettingService settingService){
        this.redisUtil = redisUtil;
        this.settingService = settingService;
        this.initLocalCache();
    }

    public void initLocalCache(){
        List<Setting> list = settingService.list();
        for (Setting setting : list) {
            localSettingMap.computeIfAbsent(setting.getModule(), l-> new HashMap<>()).put(setting.getName(),setting.getValue());
        }
    }
    public void clearSettingLoadCache(){
        localSettingMap.clear();
        localSettingMap = null;
    }

    private String getKey(String module, String name){
        return module + "||||" + name;
    }

    public Setting getSetting(String module, String name){
        Setting setting = redisUtil.getHash(CacheKeyEnum.SETTING, getKey(module , name));
        if(setting != null && NumberUtil.upper0(setting.getEncrypt())){
            setting.setValue(EncryptUtil.decryptDES(setting.getValue()));
        }
        return setting;
    }
    public void putSetting(Setting setting){
        redisUtil.setHash(CacheKeyEnum.SETTING,getKey(setting.getModule(),setting.getName()),setting);
    }

    public Map<String,Setting> getSettingMap(String module){
        Map<String, Setting> entries = redisUtil.getHashMap(CacheKeyEnum.SETTING);
        Map<String,Setting> res = new HashMap<>(5);
        for (Map.Entry<String, Setting> entry : entries.entrySet()) {
            Setting setting = entry.getValue();
            if(Objects.equals(module,setting.getModule())){
                if(NumberUtil.upper0(setting.getEncrypt())){
                    setting.setValue(EncryptUtil.decryptDES(setting.getValue()));
                }
                res.put(setting.getName(),setting);
            }
        }
        return res;
    }

    public void removeSetting(Setting setting){
        redisUtil.delHash(CacheKeyEnum.SETTING, getKey(setting.getModule(),setting.getName()));
    }
    public void load(){
        redisUtil.del(CacheKeyEnum.SETTING);
        List<Setting> settings = settingService.list();
        Map<String, Setting> em = settings.stream().collect(Collectors.toMap(o -> getKey(o.getModule(),o.getName()), o -> o, (v1, v2) -> v1));
        redisUtil.setHash(CacheKeyEnum.SETTING,em);
    }

    public String getString(String module,String name,String dv){
        String s = null;
        Map<String,String> mm = localSettingMap.get(module);
        if(mm != null){
            s = mm.get(name);
        }
        return StringTool.isEmpty(s) ? dv : s;
    }
    public Integer getInteger(String module,String name,Integer dv){
        String s = null;
        Map<String,String> mm = localSettingMap.get(module);
        if(mm != null){
            s = mm.get(name);
        }
        return StringTool.isEmpty(s) ? dv : NumberUtil.safeToInteger(s,dv);
    }
    public Long getLong(String module,String name,Long dv){
        String s = null;
        Map<String,String> mm = localSettingMap.get(module);
        if(mm != null){
            s = mm.get(name);
        }
        return StringTool.isEmpty(s) ? dv : NumberUtil.safeToLong(s,dv);
    }
    public Boolean getBoolean(String module,String name,Boolean dv){
        String s = null;
        Map<String,String> mm = localSettingMap.get(module);
        if(mm != null){
            s = mm.get(name);
        }
        return StringTool.isEmpty(s) ? dv : ObjectUtil.saveToBoolean(s,dv);
    }


}
